home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / Libraries / DCLAP 6d / dclap6d / DNet / DTCP.cpp < prev    next >
Text File  |  1996-07-05  |  18KB  |  910 lines

  1. // DTCP.cp 
  2. // by D. Gilbert, 1991-92, with help from code of Harry Chesley and others 
  3. // 1994 -- rewritten for multi-platform tcp-sockets
  4.  
  5.  
  6. #include "DTCP.h"
  7. #include <DUtil.h>
  8. #include <ncbi.h>
  9. #include <dgg.h>
  10. #include <Dversion.h>
  11.  
  12. #include "dnettcp.h"
  13.  
  14.  
  15. Local const    short        kUTCPVersion    = 3;
  16. Local const    char*        kUTCPVersionString = 
  17. #ifdef WIN_MAC
  18. "v.3.3d, Jan 95 (mac)";
  19. #endif
  20. #ifdef WIN_MSWIN
  21. "v.3.3d, Jan 95 (mswin)";
  22. #endif
  23. #ifdef WIN_MOTIF
  24. "v.3.3d, Jan 95 (xwin)";
  25. #endif
  26.  
  27.  
  28. enum tcpErrors {    
  29.     kErrConnectionBroken = -1, //common way for gopher server to end transmission 
  30.     kErrTimedOut = -2,
  31.     kErrUserBreak = -3,
  32.     kErrMemFull = -4,
  33.     kErrOpenTimeout = -5
  34.     };
  35.  
  36. Local const short        kRecvChunkSize = 500;       // bytes/ handle increment
  37. Local const    short     kTCPDefaultTimeout = 1200;    // default # ticks (1/60sec) to wait for TCP remote
  38. Local const long         kDefaultOpenDelay = 20;
  39.  
  40.         // this is a guess -- no generic way to find memory available
  41. Local const    long    kMaxReadBuffer = 4048; //32000;
  42.                         
  43.  
  44.  
  45.     // Public Global vars
  46. Global long        gTCPTimeout = kTCPDefaultTimeout;
  47.  
  48. Local short     gMacTCPRefNum = 0;        // not a global now...
  49.  
  50.     // Private global vars
  51. Local long      gMyIP = 0;
  52. Local char*         gMyDotName = NULL; 
  53. Local Boolean gResolverIsOpen = false;
  54.  
  55.  
  56.  
  57.  
  58. short OpenMacTCP()
  59. {
  60.     if (gMacTCPRefNum !=0 ) 
  61.         return 0;
  62.     else {
  63.         short err= 0;
  64.         return err;
  65.         }
  66. }
  67.  
  68. void InitializeTCP()         // InitUMacTCP()
  69. {
  70.     gMyDotName = NULL;
  71.     gMacTCPRefNum= 0;
  72.     short err= OpenMacTCP(); 
  73. }
  74.  
  75. void FinishTCP()                 // CloseDownUMacTCP()
  76. {
  77.     gMacTCPRefNum = 0;
  78. }
  79.  
  80. Boolean TCPIsItInstalled()         // IsMacTCPInstalled()
  81. {
  82.     return (0 == OpenMacTCP());
  83. }
  84.  
  85. long MyIP()
  86. {
  87.     if (!OpenMacTCP() || gMyIP)  return gMyIP;
  88.     gMyIP = MyIPaddress();
  89.     return gMyIP;
  90. }
  91.  
  92. void GetMyDotName(char* myDotName)
  93. {
  94.     if (!OpenMacTCP()) {
  95.         myDotName = gMyDotName = ".";
  96.         return;
  97.         }
  98.     if (myDotName) gMyDotName= IP2DotName(MyIP());
  99.     myDotName = gMyDotName;
  100. }    
  101.  
  102.  
  103. char* IP2DotName(long ip)
  104. {
  105.     char *name = NULL;
  106.     
  107.     // ?? do we need this proc
  108.     return name;
  109. }
  110.  
  111.  
  112. long DotName2IP(const char* name)
  113. {
  114.     return Hostname2IP( (char*)name);
  115. }
  116.  
  117.  
  118.  
  119.  
  120. // DTCP ..........................
  121.  
  122. void DTCP::Initialize()
  123. {
  124.     fSocket= -1;
  125.     fError= NULL;
  126.     fErrNo= 0;
  127.     fFailed= false;
  128.     fTimeout= gTCPTimeout;
  129.     fLastSentCRLF= false;
  130.     
  131.     fDoShowProgress= false;
  132.     fResultSize= 0;
  133.     fMaxResultSize= 0;
  134.     fResultNew= 0;
  135.     fBytesread= 0;
  136.     fResultTotal= 0; // this is now a ShowProgress::LastBytesRead counter
  137.     fLimitResultSize= 0;
  138.     fEndofMessage= false;
  139.     fResultHand= NULL;
  140.     fNullTerm= true; //??
  141.     fLastc = fLast2c= fLast3c = 0; // receive -- CRLF conversion record
  142.     fStartTime= 0;
  143.     fConnectTime= 0;
  144.  
  145.     fMessageProc = NULL;
  146.     fMessageObj = NULL;
  147.     fBreakProc = NULL;
  148.     fBreakObj = NULL;
  149.     fReadSaveLen = 0;
  150.     fReadSaveBase = NULL;
  151.     fReadSave = NULL;
  152.  
  153.     (void) OpenMacTCP();
  154. }
  155.  
  156.  
  157. DTCP::DTCP()
  158. {
  159.     Initialize();
  160. }
  161.  
  162.  
  163. DTCP::~DTCP() 
  164. {
  165.     if (fConnectionIsOpen)  
  166.         Close();
  167.     if (fStreamIsOpen)  
  168.         Release();
  169. }
  170.  
  171.  
  172. Boolean DTCP::UserBreak()
  173. {  
  174.     if (fBreakProc)
  175.         return (fBreakProc)(fBreakObj);
  176.     else
  177.         return false;
  178. }    
  179.  
  180. void DTCP::StreamYieldTime()
  181. {
  182.     if (UserBreak()) Fail(-1); //??
  183. }
  184.  
  185.  
  186. void DTCP::Fail(long errNo)
  187. {
  188.     if (errNo) {
  189.         fErrNo= errNo;
  190.         fError= NULL;
  191.         fFailed= true;
  192.         Nlm_Message (MSG_ERROR, "Network DTCP error # %d",errNo);
  193.         }
  194. }
  195.  
  196.  
  197. void DTCP::Fail(const char* msg)
  198. {
  199.     if (msg) {
  200.         fErrNo= 0;
  201.         fError= (char*) msg;
  202.         fFailed= true;
  203.         Nlm_Message (MSG_ERROR, "Network DTCP error:\n%s", (char*) msg);
  204.         }
  205. }
  206.  
  207. Boolean DTCP::Failed()
  208. {
  209.     return fFailed;
  210. }
  211.  
  212.  
  213.  
  214. void DTCP::InstallUserBreak(TCPUserBreakHandler aproc, DTaskMaster* itsObject)
  215. {
  216.     fBreakProc= aproc;
  217.     fBreakObj= itsObject;
  218. }
  219.  
  220. void DTCP::InstallMessageHandler(TCPMessageHandler aproc, DTaskMaster* itsObject)
  221. {
  222.     fMessageProc= aproc;
  223.     fMessageObj= itsObject;
  224. }
  225.  
  226. void DTCP::ShowMessage(const char* msg)
  227. {
  228.     if (fMessageProc) (fMessageProc)(fMessageObj, 0, msg);
  229. }
  230.  
  231. Boolean DTCP::IsTCPInstalled()
  232. {
  233.     return TCPIsItInstalled();
  234. }
  235.  
  236.  
  237. long DTCP::NameToAddress(const char* hostName)
  238. {
  239.     return DotName2IP(hostName);
  240. }
  241.  
  242.     // non-functional IP2DotName...
  243. char* DTCP::AddressToName(long address)
  244. {
  245.     return IP2DotName(address);
  246. }
  247.  
  248.     // non-functional IP2DotName...
  249. char* DTCP::DotAddrToName(const char* dotAddress)
  250. {
  251.     return IP2DotName( DotName2IP( dotAddress));
  252. }
  253.  
  254. char* DTCP::RemoteName()
  255. {
  256.     char* name = NULL;
  257.     if (fSocket>=0) {
  258.         const long namelen = 256;
  259.         name= (char*) MemNew(namelen);
  260.         short err= SockHostname(fSocket, name, namelen);
  261.         }
  262.     return name;
  263. }
  264.  
  265.  
  266.         // do we want both of these??
  267. long DTCP::Version()
  268. {
  269. #if 1
  270.     return kDCLAPVersion;
  271. #else
  272.     return kUTCPVersion;
  273. #endif
  274. }
  275.  
  276. const char* DTCP::VersionString()
  277. {
  278. #if 1
  279.     return kDCLAPVersionString;
  280. #else
  281.     return kUTCPVersionString;
  282. #endif
  283. }
  284.  
  285.  
  286. char* DTCP::StatusString(short state)
  287. {
  288.     switch (state) {
  289.         case kTCPlistening    : return "TCP listening";
  290.         case kTCPwaitingforopen: return "TCP waiting for open";
  291.         case kTCPopening        : return "TCP opening";
  292.          case kTCPestablished: return "TCP established";
  293.         case kTCPPleaseClose: return "TCP please close";
  294.         case kTCPclosing        : return "TCP closing";
  295.         case kTCPclosed            : return "TCP closed";
  296.         case kTCPreleased        : return "TCP released";
  297.         case kTCPUnknownState:
  298.         default                            : return "TCP unknown state";
  299.         }
  300. }
  301.  
  302.  
  303. long DTCP::Status()
  304. {
  305.     if (!fStreamIsOpen)                return kTCPreleased;
  306.     else if (!fConnectionIsOpen)     return kTCPPleaseClose;
  307.     else                                          return kTCPestablished;
  308. }
  309.  
  310. void DTCP::StatusMessage(void)
  311. {
  312.     ShowMessage( StatusString(Status()));
  313. }
  314.  
  315. Boolean DTCP::EndOfMessage()
  316. {
  317.     return fEndofMessage;
  318.     //?? return (fEndofMessage || (NewBytesReceived == 0));
  319.     //^^ bad when linefeeds are received but don't count in NewBytesRec...!!!
  320. }
  321.  
  322. void DTCP::SetEndOfMessage( Boolean isEnded)
  323. {
  324.     fEndofMessage= isEnded;
  325. }
  326.  
  327.  
  328. //ncbi.h:     time_t Nlm_GetSecs() == time() call, should be okay on all ansi c systems?
  329.  
  330. Boolean DTCP::WaitedForOpen(long delayticks)
  331. {
  332.     short        currStat, oldStat;
  333.     
  334.     oldStat= -123;
  335.     while (true) {
  336.         // Delay(5, &aTicks); << what is ncbi/generic equivalent ??
  337.         //for (aTicks= GetSecs() + 5; GetSecs() < aTicks; ) ;
  338.         
  339.         currStat= (short)Status();
  340.         if (currStat!=oldStat) ShowMessage( StatusString(currStat));
  341.         switch (currStat) {
  342.         
  343.             case kTCPestablished:  
  344. #if FIX_LATER
  345.                 //if (delayticks) 
  346.                 //for (aTicks= GetSecs() + delayticks; GetSecs() < aTicks; ) ;
  347.                 // ^^ this is TOO LONG
  348. #endif
  349.                 return true;
  350.  
  351.             case kTCPUnknownState:
  352.             case kTCPPleaseClose:
  353.             case kTCPreleased:
  354.             case kTCPclosed    :  
  355.                 Fail("Couldn't connect to TCP service.");
  356.                 Release();
  357.                 return false;
  358.                 
  359.             default: if (UserBreak()) {
  360.                 Release();
  361.                 return false;
  362.                 }
  363.             }
  364.         oldStat= currStat;
  365.         }
  366.     return false;
  367. }
  368.  
  369. Boolean DTCP::WaitedForOpen()
  370. {
  371.     return WaitedForOpen(kDefaultOpenDelay);
  372. }
  373.  
  374.  
  375.  
  376. void DTCP::SetShowProgress( Boolean turnOn)
  377. {
  378.     fDoShowProgress= turnOn;
  379. }
  380.  
  381. void DTCP::ShowProgress( long sendRecvCount)
  382. {
  383.     char msg[128];
  384.     sprintf( msg, "TCP bytes sent: %d", sendRecvCount);
  385.     ShowMessage(msg);
  386. }
  387.  
  388. void DTCP::ShowProgress()
  389. {
  390.     if (fBytesread > fResultTotal + 1024) {
  391.         ShowProgress( fBytesread);
  392.         fResultTotal= fBytesread;
  393.         }
  394. }
  395.  
  396.  
  397.  
  398.  
  399. void DTCP::Release()
  400. {
  401.     short err;
  402.     fBytesread= 0;
  403.     fStreamIsOpen = false;
  404.     if (fSocket>=0) err= SockClose(fSocket); 
  405.     fSocket= -1;
  406.     fConnectionIsOpen = false;
  407. }
  408.  
  409.  
  410.  
  411. void DTCP::Open( char* hostname, unsigned short hostport, unsigned short localport)
  412. {
  413.     fBytesread= 0;
  414.     fLastc= fLast2c= fLast3c= 0;
  415.     fConnectTime= 0;
  416.     fStartTime=    GetSecs();
  417.     fLastSentCRLF= false;
  418.     fConnectionIsOpen= false;
  419.     
  420.     fSocket= SockOpen( hostname, hostport);
  421.     if (fSocket<0) {
  422.         char buf[256];
  423.         if (!hostname) hostname="NULL";
  424.         switch (fSocket) {
  425.             case errHost        :  
  426.                 sprintf(buf, "Can't get IP# for host '%s', port %d", 
  427.                     hostname, hostport);
  428.                 Fail(buf); return;
  429.             case errSocket    : 
  430.                 Fail("Can't create IP socket"); return;
  431.             case errConnect    : 
  432.                 sprintf(buf, "Can't connect to host '%s', port %d", 
  433.                         hostname, hostport);
  434.                 Fail(buf); return;
  435.             default                    : 
  436.                 Fail("Can't open IP connection"); return;
  437.             }
  438.         }
  439.     fStreamIsOpen = true;
  440.     fConnectionIsOpen = true;
  441. }
  442.  
  443.  
  444.  
  445. // CloseConnection aborts the connection if it could not be closed
  446. void DTCP::Close()
  447. {
  448.     short err;
  449.     fConnectTime = GetSecs() - fStartTime;
  450.     if (fSocket>=0)  err= SockClose(fSocket); 
  451.     fSocket= -1;
  452.     fConnectionIsOpen = false;
  453. }
  454.  
  455.  
  456. void DTCP::Abort()
  457. {
  458.     short err;
  459.     if (fSocket>=0) err= SockClose(fSocket); 
  460.     fSocket= -1;
  461.     fConnectionIsOpen = false;
  462. }
  463.  
  464.  
  465.  
  466.  
  467.  
  468. // Send functions ......................................
  469.  
  470.  
  471. void DTCP::SendBytes(void *data, long datasize, Boolean immediately)
  472. {
  473.     long len= SockWrite( fSocket, data, datasize);
  474.     char*    pp =  (char*) data;
  475.     fLastSentCRLF= (pp[datasize-1] == kLF && pp[datasize-2] == kCR);
  476. }
  477.  
  478.  
  479. void DTCP::Send( char* cstring, Boolean immediately)
  480. {
  481.     SendBytes( cstring, StrLen(cstring), immediately);
  482. }
  483.  
  484. void DTCP::SendCRLF(Boolean EvenIfLastSendHadCRLF, Boolean immediately)
  485. {
  486.     static char    buf[2] = {kCR,kLF};
  487.     if (EvenIfLastSendHadCRLF || !fLastSentCRLF)
  488.         SendBytes( &buf, 2, immediately);
  489. }
  490.  
  491. void DTCP::SendStr( char* s, Boolean addCRLF, Boolean immediately)
  492. {
  493.     SendBytes( s, strlen(s), immediately);
  494.     if (addCRLF)    SendCRLF( true, immediately);
  495. }
  496.  
  497.  
  498.  
  499.  
  500.  
  501.  
  502.  
  503.  
  504. // Receive status functions ......................................
  505.  
  506. long DTCP::CharsAvailable() 
  507. {        
  508.     if (!fStreamIsOpen) 
  509.         return 0;
  510.     else if (!fConnectionIsOpen)  
  511.         return 0;
  512.     else {
  513.         long charsleft =  0;
  514.         
  515.         if (fReadSave) charsleft= fReadSaveLen;
  516.         
  517.             // ?? how do we deal w/ this in sockets ??
  518.             // do we need to use select(n, readfds, writefds, errfds, timeout);
  519.             // doesn't select() set a file descripttor for async operations??
  520. #if 0
  521.         long readarray[1] = { fSocket };
  522.         long maxtime = 1;
  523.         short result= SockSelect( 1, readarray, NULL, NULL, maxtime);
  524.         if (result > 0) charsleft++; // don't know how many...
  525. #endif
  526.  
  527.         return charsleft;
  528.         }
  529. }
  530.  
  531. void DTCP::EatResponseLine(void)
  532. {
  533.     long bytesread;
  534.     (void) MemFree( RecvLine()); // hanging up here !!?? in sendmail
  535.     (void) MemFree( RecvChars( CharsAvailable(), bytesread ));    
  536. }
  537.  
  538.  
  539. long DTCP::TotalBytesReceived()
  540. // total over life of the DTCP (since init), or multiple calls to RecvUpTo, RecvChunk ...
  541. {
  542.     return fBytesread; // fResultTotal;
  543. }
  544.  
  545. long DTCP::NewBytesReceived()
  546. // total only for last read 
  547. {
  548.     return fResultNew;
  549. }
  550.  
  551. void DTCP::NullTerm( Boolean turnon)
  552. {
  553.     fNullTerm = turnon;
  554. }
  555.  
  556. long DTCP::ConnectTime()
  557. {
  558.     if (fConnectionIsOpen) fConnectTime = GetSecs() - fStartTime;
  559.     return fConnectTime;
  560. }
  561.  
  562.  
  563.  
  564.  
  565. // Receive functions ......................................
  566.  
  567.  
  568. short DTCP::ReceiveData(void *data, long datasize, long &bytesReceived, Boolean stopatlf)
  569. {
  570.     short    err= 0;
  571.     long startTick= GetSecs();
  572.     long oldBytes = fBytesread;
  573.     Boolean done    = datasize < 1;
  574.     bytesReceived = 0;
  575.     char*    datap        = (char*) data;
  576.         
  577.     long count;
  578.     
  579.     if (fReadSave) {
  580.         // read from local buffer...
  581.         count= Min( datasize, fReadSaveLen);
  582.         if (stopatlf) {
  583.             char* lfp= (char*) MemChr( fReadSave, kLF, count);
  584.             if (lfp) { 
  585.                 count= lfp - fReadSave + 1;
  586.                 done= true;
  587.                 }
  588.             }
  589.         MemCpy( datap, fReadSave, count);
  590.         datap += count;
  591.         bytesReceived += count;
  592.         datasize -= count;
  593.         if (datasize<1) done= true;
  594.         fReadSaveLen -= count;
  595.         if (fReadSaveLen > 0) {
  596.             fReadSave += count; // just push up pointer... keep fReadSaveBase around
  597.             }
  598.         else {
  599.             fReadSaveBase= (char*) MemFree( fReadSaveBase);
  600.             fReadSave= fReadSaveBase;
  601.             fReadSaveLen= 0;
  602.             }
  603.         }
  604.  
  605.     while ( !done ) {
  606.         count= SockRead( fSocket, datap, datasize);
  607.       if (count > 0) {
  608.       
  609.             if (stopatlf) {
  610.                 char *lfp= (char*) MemChr(datap, kLF, count);
  611.                 if (lfp) {
  612.                     long newcount= lfp - datap + 1;
  613.                     if (newcount < count) {
  614.                         fReadSaveLen= count - newcount;
  615.                         fReadSaveBase=    (char*) MemDup( lfp+1, fReadSaveLen);
  616.                         fReadSave= fReadSaveBase;
  617.                         count= newcount;
  618.                         }
  619.                     done= true;
  620.                     }
  621.                 }
  622.                 
  623.             datap     += count;
  624.             bytesReceived += count;
  625.             datasize -= count;
  626.             if (datasize<1) done= true;
  627.             }
  628.         else {
  629.             done= true; 
  630.             if (count < 0) { err= count; fEndofMessage= true; } //??
  631.             else if (count == 0) fEndofMessage= true; // !! need this for unix/win_motif
  632.             }
  633.         }
  634.     
  635.     fBytesread= oldBytes + bytesReceived;
  636.         
  637.     StreamYieldTime();
  638.     return err;
  639. }
  640.  
  641.  
  642.  
  643.  
  644.  
  645.         //     CAN'T RELY ON NULL TERMINATED STRINGS w/ BINARY DATA !!!
  646.             
  647.     
  648. char* DTCP::ReadWithChecks( 
  649.                         ulong& bufsize,
  650.                         long     expectedbytes/* = kTCPStopAtclose*/, 
  651.                         Boolean convertnewline/* = false*/, 
  652.                         long     maxbytes/* = 0*/, 
  653.                         char* oldbuffer/* = NULL*/)
  654. {
  655.     enum { kDropChar = 22 };
  656.     long    bytesread = 0, bufadditions = 0, newbytes= 0;
  657.     long     oldbytes= fBytesread;
  658.     Boolean stopAtdotcrlf = (expectedbytes == kTCPStopAtdotcrlf);
  659.     Boolean done = false, dodropchar= false;
  660.     short    err = 0;
  661.     long     count, newcount;
  662.     char * bufat, * from, * tob;
  663.     long     startTick = GetSecs();
  664.  
  665.     if (maxbytes <= 0) maxbytes= kMaxReadBuffer;
  666.     else maxbytes= Min(maxbytes, kMaxReadBuffer);
  667.     fResultNew= 0; //??
  668.  
  669.     if (oldbuffer == NULL) { 
  670.         bufsize= 0; 
  671.         oldbuffer= (char*) MemGet(1, true);
  672.         }
  673.     else {
  674.         // --- NOW, assume caller passes true size of oldbuffer -- for data w/ nulls
  675.         //bufsize= strlen(oldbuffer); // <<!!! Implies null term !!!
  676.       //if (bufsize && oldbuffer[bufsize-1] == 0) bufsize--;
  677.         }
  678.         
  679.     gErrorManager->TurnOff();        
  680.     do {
  681.         count= maxbytes - newbytes; 
  682.         if (count>0) {
  683.             bufat= (char*) MemMore( oldbuffer, bufsize + count + 1);
  684.             if (bufat) oldbuffer= bufat;
  685.             else { 
  686.                 fResultNew= -1; // flag for out-of-mem
  687.                 goto finish;         // out of mem
  688.                 }
  689.             bufat= oldbuffer + bufsize;
  690.             newcount = 0;
  691.  
  692.             err= ReceiveData( bufat, count, newcount, stopAtdotcrlf);
  693.             
  694.             if (newcount>0 && stopAtdotcrlf && (bufat[0] == '.')) {
  695.                 if (bufat[1] == kCR || bufat[1] == kLF) {
  696.                     newcount= 0;
  697.                     fEndofMessage= true;
  698.                     }
  699.                 else if (bufat[1] == '.') {
  700.                     bufat[0] = kDropChar;
  701.                     dodropchar= true;
  702.                     }
  703.                 } 
  704.             count= newcount;
  705.             
  706.             bufsize  += count;
  707.             newbytes += count;
  708.             StreamYieldTime();
  709.             }
  710.     } while (err == 0 && count > 0);
  711.     fResultNew = newbytes;
  712.         
  713. finish:
  714.     gErrorManager->TurnOn();        
  715.     
  716.     if (dodropchar) {
  717.         tob= from= oldbuffer;
  718.         for (count= 0; count<bufsize; count++, from++) {
  719.             if (*from != kDropChar)  *tob++= *from;
  720.             }
  721.         *tob= 0;
  722.         bufsize= tob - oldbuffer; 
  723.         dodropchar= false;
  724.         }
  725.         
  726.     if (convertnewline && bufsize) { 
  727.         tob= from= oldbuffer;
  728.         
  729.         if (LineEndSize == 2) { // what the net lineend is
  730.             if (LineEnd[0] == kCR && LineEnd[1] == kLF) ;
  731.             else ; // convert CRLF to LineEnd
  732.             }
  733.             
  734.         else if (LineEndSize == 1) {
  735.  
  736.             if (*LineEnd == kLF) {
  737.                 for (count= 0; count<bufsize; count++, from++) {
  738.                     if (*from != kCR) 
  739.                         *tob++= *from;
  740.                   else if (from[1] != kLF) 
  741.                       *tob++= kLF;  // fails at count==bufsize-1
  742.                   }
  743.                 }
  744.                 
  745.             else if (*LineEnd == kCR) {
  746.                 for (count= 0; count<bufsize; count++, from++) {
  747.                     if (*from != kLF) 
  748.                         *tob++= *from;
  749.                   else if (from[-1] != kCR) 
  750.                       *tob++= kCR;   
  751.                   }
  752.                 }
  753.  
  754.             *tob= 0;
  755.             bufsize= tob - oldbuffer; 
  756.             }
  757.         }    
  758.         
  759.             // shrink it down to bufsize..
  760.     oldbuffer= (char*) MemMore( oldbuffer, bufsize + 1);
  761.     if (true) { //fNullTerm !!!
  762.         oldbuffer[bufsize] = '\0'; // always now, no such GetPtrSize(p) for generic systems
  763.         }
  764.  
  765.     if (err != 0)  {
  766. #if FIX_LATER
  767.         fEndofMessage= (Status() != kTCPestablished);
  768. #else
  769.         fEndofMessage= true;
  770. #endif
  771.         }
  772.         
  773.     return oldbuffer;
  774. }
  775.  
  776.  
  777.  
  778.  
  779. short DTCP::RecvByte()
  780. {
  781.     unsigned char b;
  782.     long bytesread= 0;
  783.     short err= ReceiveData( &b, 1, bytesread);
  784.     if (bytesread>0) return b; 
  785.     else return -1;            
  786. }
  787.  
  788.  
  789. char* DTCP::RecvLine() // read up to kLF 
  790. {
  791.     const    short    kBufSize = 511;
  792.     char    buf[kBufSize+1];
  793.      short    err= 0;
  794.      
  795.     if (!fConnectionIsOpen) return false;
  796.     fResultSize= 0;
  797.     fMaxResultSize= 0;
  798.     fResultNew= fResultSize;  //save for close calculation
  799.     fEndofMessage= false;
  800.  
  801.     long     bytesread = 0;
  802.     err= ReceiveData( buf, kBufSize, bytesread, true);
  803.     if (bytesread > 0) {
  804.         fResultSize += bytesread;
  805.         fResultNew = fResultSize;
  806.         buf[bytesread]= 0;
  807.         return (char*)MemDup(buf,bytesread+1);
  808.         }
  809.     else
  810.         return NULL;
  811. }
  812.  
  813.  
  814.   
  815. char* DTCP::RecvChars(long readCount, long& numread)
  816.     long  thisread;
  817.     long  bufsize= readCount;
  818.     short err= 0;
  819.     
  820.     numread = 0;
  821.     if (!fConnectionIsOpen) return NULL; 
  822.     gErrorManager->TurnOff();        
  823.     fResultHand= (char*) MemNew(bufsize+1);
  824.     gErrorManager->TurnOn();
  825.     if (!fResultHand) 
  826.         return NULL;
  827.         
  828.     char* p= fResultHand;
  829.     if (readCount > 0) do {
  830.         thisread= 0;
  831.         err= ReceiveData( p, bufsize, thisread);
  832.         p += thisread;
  833.         bufsize -= thisread;
  834.         numread += thisread;
  835.     } while (thisread > 0 && bufsize > 0);
  836.         
  837.     if (true) { //fNullTerm)
  838.         fResultHand[numread] = '\0';
  839.         }
  840.     return fResultHand;
  841. }
  842.  
  843.  
  844. #if FIX_MAYBE_LATER_OR_TRASH
  845.  
  846. char* DTCP::RecvChunk( long maxChunk, char* oldChunk)
  847. {    
  848.     Boolean done; 
  849.     short err= 0;
  850.     long    thisread, count, oldchunksize, newchunksize= 0;
  851.      // note: maxChunk >= newchunksize, oldchunksize is separate
  852.     
  853.     fResultNew= 0;
  854.     fResultHand= oldChunk;
  855.     if (!fConnectionIsOpen) return oldChunk;
  856.     
  857.     if (maxChunk <= 0) 
  858.         maxChunk = kMaxReadBuffer; //maxChunk= FreeMem() - (FreeMem() / 5); 
  859.     
  860.     if (oldChunk == NULL) { 
  861.         oldchunksize= 0; 
  862.         oldChunk= (char*) MemNew(oldchunksize+1);
  863.         oldChunk[oldchunksize]= '\0';        
  864.         }
  865.     else 
  866.         oldchunksize= strlen( oldChunk); // !! this implies NULL termination for all data !
  867.  
  868.     gErrorManager->TurnOff();        
  869.     do {
  870.         //count= CharsAvailable();
  871.         //if (count+newchunksize > maxChunk) count= maxChunk-newchunksize;
  872.         count= maxChunk - newchunksize;
  873.         if (count>0) {
  874.             
  875.             char* p= (char*) MemMore( oldChunk, oldchunksize + newchunksize + count + 1);
  876.             if (p) oldChunk= p;
  877.             else { // out of memory...
  878.                 fResultNew= -1;
  879.                 goto finish;
  880.                 }
  881.             p= oldChunk + oldchunksize + newchunksize;
  882.             thisread = 0;
  883.             err= ReceiveData( p, count, thisread);
  884.             newchunksize += thisread;
  885.             }
  886.  
  887.         fEndofMessage= (Status() != kTCPestablished);
  888.         if (fDoShowProgress) ShowProgress(); 
  889.         done= (err != 0 || newchunksize >= maxChunk || thisread < 1);
  890.         if (UserBreak()) {
  891.             done= true;
  892.             Fail("User break");  // ?? fail or proceed w/ short read?
  893.             }
  894.     } while (!(done || fEndofMessage));     
  895.     fResultNew= newchunksize;
  896.     
  897. finish:
  898.     gErrorManager->TurnOn();        
  899.  
  900.     if (true) { //fNullTerm) 
  901.         oldChunk[oldchunksize + newchunksize] = '\0';
  902.         }
  903.     fResultHand= oldChunk;
  904.     return oldChunk;
  905. }
  906.  
  907. #endif
  908.  
  909.